package com.weike.test.service;

import com.weike.test.config.DateBaseConnectionFactory;
import com.weike.test.mapper.BaseMapper;
import com.weike.test.util.AliOssUtil;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class CustomerService {

    @Autowired
    private AliOssUtil aliOssUtil;

    @Autowired
    private BaseMapper baseMapper;

    /**
     * 将AI生成的前端代码上传到阿里云OSS
     *
     * @param codeStr AI生成的前端代码字符串
     * @return 上传成功后的OSS访问URL
     */
    @Tool(description = "用于ai生成的前端代码转化成文件上传到oss上，返回上传成功的地址，你需要把上传成功的文件地址返回给用户")
    public String uploadAssetsToOss(String codeStr) {
        try {
            // 生成唯一的文件名，这里使用时间戳加随机数
            String timestamp = String.valueOf(System.currentTimeMillis());
            String randomNum = String.valueOf((int)(Math.random() * 10000));
            String objectName = "ai-generated/frontend-" + timestamp + "-" + randomNum + ".html";

            // 将代码字符串转换为字节数组
            byte[] codeBytes = codeStr.getBytes("UTF-8");

            // 调用AliOssUtil上传文件
            String ossUrl = aliOssUtil.upload(codeBytes, objectName);

            return ossUrl.replace("miaoying-yuanding-space.oss-cn-beijing.aliyuncs.com" , "miaoyingassets.yuanding.space")
                    .replace("https:" , "http:");
        } catch (Exception e) {
            throw new RuntimeException("上传前端代码到OSS失败: " + e.getMessage(), e);
        }
    }

    @Tool(description = "获取所有的数据库名，用于后续执行executeQuery与executeInsert工具，该方法无需传参")
    public List<String> listDataBase() {
        return baseMapper.selectAllDataBase();
    }

    @Tool(description = "执行查询sql,返回值是List执行结果,使用该方法需要传入需要操作的数据库名及需要执行的sql。")
    public List<Map<String, Object>> executeQuery(String dataBaseName ,String sql) {

        try (Connection conn = DateBaseConnectionFactory.getConnection(dataBaseName);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            List<Map<String, Object>> result = new ArrayList<>();
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();

            // 遍历结果集
            while (rs.next()) {
                Map<String, Object> row = new HashMap<>();
                for (int i = 1; i <= columnCount; i++) {
                    String columnName = metaData.getColumnLabel(i);
                    Object value = rs.getObject(i);
                    row.put(columnName, value);
                }
                result.add(row);
            }
            return result;
        } catch (SQLException e) {
            throw new RuntimeException("查询执行失败: " + sql, e);
        }
    }

    @Tool(description = "执行插入修改sql,返回值是插入执行结果,使用该方法需要传入需要操作的数据库名及需要执行的sql。")
    public int executeInsert(String dataBaseName,String sql) {
        try (Connection conn = DateBaseConnectionFactory.getConnection(dataBaseName);
             Statement stmt = conn.createStatement()) {
            return stmt.executeUpdate(sql);
        } catch (SQLException e) {
            throw new RuntimeException("插入/更新执行失败: " + sql, e);
        }
    }

    /**
     * 执行系统命令并返回命令的输出结果
     * @param command 要执行的系统命令，例如 "dir" 或 "start notepad"
     * @return 命令执行的输出结果字符串，如果执行失败则返回错误信息
     */
    @Tool(description = "执行系统命令并返回输出结果，可传入 command 字符串要执行的系统命令，例如 \"dir\" 或 \"start notepad\"")
    public String executeCommand(String command) {
        try {
            // 使用 ProcessBuilder 执行命令
            ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
            processBuilder.redirectErrorStream(true); // 合并错误流和输出流
            Process process = processBuilder.start();

            // 读取命令的输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            StringBuilder output = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }

            // 等待命令执行完成并检查退出码
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                return "命令执行失败，退出码: " + exitCode;
            }

            return output.toString();
        } catch (IOException e) {
            return "执行命令时发生 IO 异常: " + e.getMessage();
        } catch (InterruptedException e) {
            return "命令执行被中断: " + e.getMessage();
        }
    }

/*    *//**
     * 创建文件并写入指定内容（分块写入）
     *
     * @param filePath 文件的目标路径
     * @param content 要写入文件的内容
     * @return boolean 表示文件创建和写入是否成功
     * @throws RuntimeException 如果文件操作失败
     *//*
    @Tool(description = "创建文件并分块写入内容，返回操作是否成功")
    public boolean createFile(String filePath, String content) {
        log.info(new JSONObject(new HashMap<String , String>(){{put("content" , "写入文件的内容"+ content);}}).toString());

        try (FileWriter writer = new FileWriter(filePath)) {
            int chunkSize = 1024; // 每次写入的块大小（1KB）
            int length = content.length();

            for (int i = 0; i < length; i += chunkSize) {
                int end = Math.min(i + chunkSize, length);
                writer.write(content, i, end - i);
                writer.flush(); // 每块写入后刷新
            }
            return true;
        } catch (IOException e) {
            throw new RuntimeException("文件创建或写入失败: " + filePath, e);
        }
    }

    *//**
     * 重载方法，支持追加写入（分块写入）
     *
     * @param filePath 文件路径
     * @param content 内容
     * @param append 是否追加到文件末尾
     * @return boolean 操作是否成功
     *//*
    @Tool(description = "创建文件并分块写入内容，支持追加模式，返回操作是否成功")
    public boolean createFile2(String filePath, String content, boolean append) {
        log.info(new JSONObject(new HashMap<String , String>(){{put("content" , "写入文件的内容"+ content);}}).toString());
        try (FileWriter writer = new FileWriter(filePath, append)) {
            int chunkSize = 1024; // 每次写入的块大小（1KB）
            int length = content.length();

            for (int i = 0; i < length; i += chunkSize) {
                int end = Math.min(i + chunkSize, length);
                writer.write(content, i, end - i);
                writer.flush(); // 每块写入后刷新
            }
            return true;
        } catch (IOException e) {
            throw new RuntimeException("文件创建或写入失败: " + filePath, e);
        }
    }*/
}